package com.timedomain.him.remake.ui;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.ContactsContract;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.timedomain.him.remake.R;
import com.timedomain.him.remake.utils.*;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


public class DataPackActivity extends BaseActivity {
    ListView listView = null;

    public static void startNoDatapack(Context ctx) {
        Intent i = new Intent(ctx, DataPackActivity.class);
        i.putExtra("nofile", true);
        ctx.startActivity(i);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_datapack);
        listView = findViewById(R.id.listDataPack);
        if (getIntent().getBooleanExtra("nofile", false)) {
            loadData();
        } else {
            processDataPack();
        }
    }


    public void processDataPack() {
        Intent i = getIntent();
        Uri data = i.getData();
        if (data == null) {
            new AlertDialog.Builder(this)
                    .setOnDismissListener(dialog -> finish())
                    .setMessage("无法读取数据包信息")
                    .setNegativeButton(android.R.string.ok, null)
                    .create().show();
        }
        File destDir = new File(getCacheDir(), "datapackcache");
        if (!destDir.exists()) {
            destDir.mkdirs();
        }
        destDir = new File(destDir, "c_" + System.currentTimeMillis());
        if (!destDir.exists()) {
            destDir.mkdirs();
        }

        File finalDestDir = destDir;
        RunUtils.runProgressDialog(this, "正在读取数据包信息...", () -> {
            try (InputStream instream = getContentResolver().openInputStream(data); ZipInputStream zis = new ZipInputStream(instream)) {
                ZipEntry ze;
                while ((ze = zis.getNextEntry()) != null) {
                    if (ze.isDirectory()) {
                        continue;
                    }
                    File targetFile = new File(finalDestDir, ze.getName());
                    if (!targetFile.getParentFile().exists()) {
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();

                    try (FileOutputStream fos = new FileOutputStream(targetFile)) {
                        int len = 0;
                        byte[] buf = new byte[2048];
                        while ((len = zis.read(buf, 0, buf.length)) > 0) {
                            fos.write(buf, 0, len);

                        }
                        fos.flush();
                    }


                }

                // file already extracted here.
                // beginning read metadata.
                Gson gson = new Gson();
                DataPackManager.DataPackMetadata metadata =
                        gson.fromJson(PhysicalFileUtils.readAllText(new File(finalDestDir, "meta.json"))
                                , DataPackManager.DataPackMetadata.class);
                if (metadata == null || metadata.id == null || !Pattern.matches("^[A-Za-z0-9_]{1,56}$", metadata.id)) {
                    throw new InvalidObjectException("ID格式错误");
                }

                {
                    for (DataPackManager.DataPackMetadata installedDataPack : DataPackManager.getInstalledDataPacks()) {
                        if (installedDataPack.id.equals(metadata.id)) {
                            if (installedDataPack.version > metadata.version) {
                                throw new InvalidObjectException("已安装更新的数据包.");
                            }
                        }
                    }

                    if (DataPackManager.getOfficialReleaseDataPack().id.equals(metadata.id)) {
                        if (DataPackManager.getOfficialReleaseDataPack().version > metadata.version) {
                            throw new InvalidObjectException("已安装更新的数据包.");
                        }
                    }
                }
                // begin prompt for data pack installing.
                runOnUiThread(() -> beforeInstall(finalDestDir, metadata));


            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() -> {
                    new AlertDialog.Builder(this)
                            .setOnDismissListener(dialog -> finish())
                            .setTitle("无法读取数据")
                            .setMessage("文件可能已经损坏。\n" + e.getClass().getName() + System.lineSeparator() + e.getLocalizedMessage())
                            .setNegativeButton(android.R.string.ok, null)
                            .create().show();
                });
            }


        });

    }

    public void beforeInstall(File pendingDir, DataPackManager.DataPackMetadata metadata) {
        File targetFile = DataPackManager.getDataPackDir(metadata.id);
        boolean exists = targetFile.exists();
        new AlertDialog.Builder(this)
                .setTitle("数据包: " + metadata.name)
                .setMessage(exists ? "是否更新此数据包？" : "是否安装此数据包？")
                .setCancelable(false)
                .setPositiveButton("安装", (dialog, which) -> RunUtils.runProgressDialog(this, "正在安装...", () -> {
                    if (exists) {
                        PhysicalFileUtils.deleteDirectory(targetFile);
                    }
                    pendingDir.renameTo(targetFile);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    DataPackManager.notifyDataPackChanged(this);
                    runOnUiThread(() -> {
                        showToast("数据包安装成功。");
                        loadData();
                    });
                }))
                .setNegativeButton("取消", (dialog, which) ->
                        RunUtils.runLongWorkOnUIThread(() ->
                                PhysicalFileUtils.deleteDirectory(pendingDir)))
                .create().show();
    }

    public void loadData() {
        var installed = new ArrayList<DataPackManager.DataPackMetadata>();
        installed.add(DataPackManager.getOfficialReleaseDataPack());
        installed.addAll(DataPackManager.getInstalledDataPacks());
        listView.setAdapter(new DataPackAdapter(installed));
        listView.setVisibility(listView.getCount() > 0 ? View.VISIBLE : View.GONE);
        findViewById(R.id.listDataPackEmptyHint).setVisibility(listView.getCount() <= 0 ? View.VISIBLE : View.GONE);
    }


    private void dataPackItemClick(DataPackManager.DataPackMetadata dpm) {
        var dlg = new AlertDialog.Builder(this)
                .setTitle("数据包详情")
                .setMessage(
                        "标题：" + dpm.name
                                + "\nID: " + dpm.id
                                + "\n版本: " + dpm.version
                                + "\n介绍: " + dpm.description
                )
                .setPositiveButton(android.R.string.ok, null)
                .setNegativeButton(android.R.string.cancel, null);
        if (! dpm.id.equals(DataPackManager.getOfficialReleaseDataPack().id)) {
            dlg.setNeutralButton("卸载", (dialog, which) -> {
                new AlertDialog.Builder(this)
                        .setTitle(dpm.name)
                        .setMessage(
                                "是否卸载这个数据包？"
                        )
                        .setPositiveButton(android.R.string.ok, (d, i) -> {
                            RunUtils.runProgressDialog(this, "正在卸载...", () -> {
                                File f = DataPackManager.getDataPackDir(dpm.id);
                                PhysicalFileUtils.deleteDirectory(f);

                                runOnUiThread(() -> {
                                    DataPackManager.notifyDataPackChanged(this);
                                    showToast("已卸载 " + dpm.name);
                                    loadData();
                                });

                            });

                        })
                        .setNegativeButton(android.R.string.cancel, null)
                        .create().show();


            });
        }
        dlg.create().show();
    }

    class DataPackAdapter extends ArrayAdapter<DataPackManager.DataPackMetadata> {
        public DataPackAdapter(@NonNull List<DataPackManager.DataPackMetadata> objects) {
            super(DataPackActivity.this, R.layout.list_emergency, objects);
        }

        @NonNull
        @Override
        public View getView(int position, @androidx.annotation.Nullable View convertView, @NonNull ViewGroup parent) {
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.list_emergency, null, false);
                ((ImageButton) convertView.findViewById(R.id.listEmergencyItemPlayButton))
                        .setImageResource(R.drawable.forward);
            }
            final var item = getItem(position);
            ((TextView) convertView.findViewById(R.id.listEmergencyItemTitle))
                    .setText(item.name + " - v" + item.version);
            ((TextView) convertView.findViewById(R.id.listEmergencyItemDescription))
                    .setText(item.description);
            convertView.findViewById(R.id.listEmergencyItemPlayButton)
                    .setOnClickListener((v) -> {
                        dataPackItemClick(item);
                    });
            return convertView;
        }
    }

}
